package com.ailesson.video.service.impl;

import com.ailesson.common.except.GlobalErrorCodeConstants;
import com.ailesson.common.except.ServiceException;
import com.ailesson.video.dto.CourseDto;
import com.ailesson.video.entity.CourseDescriptionEntity;
import com.ailesson.video.entity.SubjectEntity;
import com.ailesson.video.entity.TeacherEntity;
import com.ailesson.video.enums.CourseStateEnum;
import com.ailesson.video.model.reply.ChapterReply;
import com.ailesson.video.model.reply.CourseDescriptionReply;
import com.ailesson.video.model.reply.CoursePublishReply;
import com.ailesson.video.service.*;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.BeanUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;

import com.ailesson.video.mapper.CourseMapper;
import com.ailesson.video.entity.CourseEntity;
import com.ailesson.video.model.req.CourseQueryReq;
import com.ailesson.video.model.req.CourseReq;
import com.ailesson.video.model.reply.CourseReply;
import com.ailesson.common.reply.PageResult;
import cn.hutool.core.collection.CollectionUtil;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Service
public class CourseServiceImpl extends ServiceImpl<CourseMapper, CourseEntity> implements CourseService {

    @Autowired
    private TeacherService teacherService;

    @Autowired
    private SubjectService subjectService;
    @Autowired
    private CourseDescriptionService courseDescriptionService;

    @Autowired
    private VideoService videoService;
    @Autowired
    private ChapterService chapterService;


    @Override
    public PageResult queryPage(CourseQueryReq params) {
       Page pageTmp = Page.of(params.getPageNo(),params.getPageSize());
       IPage<CourseEntity> page = this.page(
               pageTmp,
               new LambdaQueryWrapper<CourseEntity>().orderByDesc(CourseEntity::getId)
                       .eq(params.getSubjectId() != null,CourseEntity::getSubjectId,params.getSubjectId())
                       .eq(params.getTeacherId() != null,CourseEntity::getTeacherId,params.getTeacherId())
                       .eq(params.getSubjectParentId() != null,CourseEntity::getSubjectParentId,params.getSubjectParentId())
                       .like(StringUtils.isNotBlank(params.getTitle()),CourseEntity::getTitle,params.getTitle())
       );
       List<CourseReply> replyList = Collections.EMPTY_LIST;
       if (CollectionUtil.isNotEmpty(page.getRecords())){
           replyList = page.getRecords().stream().map(x -> {
               CourseReply reply = new CourseReply();
               BeanUtils.copyProperties(x, reply);
               this.getNameById(reply);
               return reply;
           }).collect(Collectors.toList());
       }
       return new PageResult<>(replyList,page.getTotal(),page.getPages());
    }

    private void getNameById(CourseReply reply) {
        if (reply.getTeacherId() != null){
            Optional<TeacherEntity> oneOpt = teacherService.getOneOpt(new LambdaQueryWrapper<TeacherEntity>()
                    .select(TeacherEntity::getName).eq(TeacherEntity::getId, reply.getTeacherId()));
            if (oneOpt.isPresent()){
                reply.setTeacherName(oneOpt.get().getName());
            }
        }
        if (reply.getSubjectId() != null){
            Optional<SubjectEntity> oneOpt = subjectService.getOneOpt(new LambdaQueryWrapper<SubjectEntity>()
                    .select(SubjectEntity::getTitle).eq(SubjectEntity::getId, reply.getSubjectId()));
            if (oneOpt.isPresent()){
                reply.setSubjectTitle(oneOpt.get().getTitle());
            }
        }
        if (reply.getSubjectParentId() != null){
            Optional<SubjectEntity> oneOpt = subjectService.getOneOpt(new LambdaQueryWrapper<SubjectEntity>()
                    .select(SubjectEntity::getTitle).eq(SubjectEntity::getId, reply.getSubjectParentId()));
            if (oneOpt.isPresent()){
                reply.setSubjectParentTitle(oneOpt.get().getTitle());
            }
        }
    }

    @Override
    public CourseReply info(Long id,boolean isDescript) {
        CourseEntity entity = this.getById(id);
        if (entity != null){
            CourseReply reply = new CourseReply();
            BeanUtils.copyProperties(entity, reply);
            if (isDescript){
                CourseDescriptionEntity description = courseDescriptionService.getById(id);
                if (description != null){
                    reply.setDescription(description.getDescription());
                }
            }
            return reply;
        }
        return null;
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    @Override
    public void update(CourseReq course) {
        if (course.getId() == null || course.getId() <= 0){
            throw new ServiceException(GlobalErrorCodeConstants.ID_EMPTY_ERROR);
        }
        CourseEntity entity = this.getById(course.getId());
        if (entity == null){
            throw new ServiceException(GlobalErrorCodeConstants.NOT_EXISTS_ERROR);
        }
        BeanUtils.copyProperties(course, entity);
        this.updateById(entity);
        if (StringUtils.isNotEmpty(course.getDescription())){
            long count = courseDescriptionService.count(new LambdaQueryWrapper<CourseDescriptionEntity>()
                    .eq(CourseDescriptionEntity::getId, entity.getId()));
            if (count > 0){
                courseDescriptionService.lambdaUpdate().eq(CourseDescriptionEntity::getId,entity.getId())
                        .set(CourseDescriptionEntity::getDescription,course.getDescription())
                        .update();
            }else{
                CourseDescriptionEntity descriptionEntity = new CourseDescriptionEntity();
                descriptionEntity.setId(entity.getId());
                descriptionEntity.setDescription(course.getDescription());
                courseDescriptionService.save(descriptionEntity);
            }
        }
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    @Override
    public Long add(CourseReq course) {
        course.setId(null);
        CourseEntity entity = new CourseEntity();
        BeanUtils.copyProperties(course, entity);
        this.save(entity);
        if (StringUtils.isNotEmpty(course.getDescription())){
            CourseDescriptionEntity descriptionEntity = new CourseDescriptionEntity();
            descriptionEntity.setId(entity.getId());
            descriptionEntity.setDescription(course.getDescription());
            courseDescriptionService.save(descriptionEntity);
        }
        return entity.getId();
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    @Override
    public void deleteById(Long id) {
        //删除节段视频
        videoService.deleteByCourseId(id);
        //删除章节
        chapterService.deleteByCourseId(id);
        //删除课程描述
        courseDescriptionService.removeById(id);
        //删除课程
        this.removeById(id);
    }

    @Override
    public CoursePublishReply getCoursePublishById(Long id) {
        return baseMapper.getCoursePublishById(id);
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    @Override
    public void publishCourse(Long id) {
         this.lambdaUpdate().eq(CourseEntity::getId,id)
                 .set(CourseEntity::getStatus, CourseStateEnum.PUBLISH.getCode())
                 .set(CourseEntity::getPublishTime, LocalDateTime.now())
                 .update();
    }

    @Override
    public List<CourseDto> findByKeyword(String keyword) {
        List<CourseEntity> list = this.list(new LambdaQueryWrapper<CourseEntity>().like(CourseEntity::getTitle, keyword));
        return list.stream().map(x -> {
            CourseDto dto = new CourseDto();
            BeanUtils.copyProperties(x, dto);
            return dto;
        }).collect(Collectors.toList());
    }

    @Override
    public Map<String, Object> getInfoById(Long courseId) {
        //view_count浏览数量 +1
        CourseEntity course = this.lambdaQuery().select(CourseEntity::getViewCount)
                .eq(CourseEntity::getId,courseId)
                .one();
        if (course != null){
            this.lambdaUpdate()
                    .eq(CourseEntity::getId,courseId)
                    .set(CourseEntity::getViewCount,(course.getViewCount() == null?0:course.getViewCount())+1)
                    .update();
        }
        //根据课程id查询
        //课程详情数据
        CourseReply courseVo = baseMapper.selectCourseById(courseId);
        //课程章节小节数据
        List<ChapterReply> chapterVoList = chapterService.getTreeList(courseId);
        //课程描述信息
        CourseDescriptionReply courseDescription = courseDescriptionService.info(courseId);
        //课程所属讲师信息
        TeacherEntity teacher = teacherService.getById(course.getTeacherId());

        //封装map集合，返回
        Map<String,Object> map = new HashMap();
        map.put("courseVo", courseVo);
        map.put("chapterVoList", chapterVoList);
        map.put("description", null != courseDescription ? courseDescription.getDescription() : "");
        map.put("teacher", teacher);
        map.put("isBuy", false);//是否购买
        return map;
    }
}